Popular Searches
Popular Course Categories
Popular Courses

Flutter Buttons

Flutter UI Components

Flutter Buttons – Detailed Notes

Buttons are one of the most important interactive elements in a Flutter application. They allow users to perform actions such as submitting forms, opening screens, saving information, downloading files, adding products to a cart, deleting records, and navigating through an application.

Flutter provides several Material button widgets, including ElevatedButton, FilledButton, OutlinedButton, TextButton, IconButton, and FloatingActionButton. Modern Flutter uses these button widgets instead of the older FlatButton, RaisedButton, and OutlineButton widgets. :contentReference[oaicite:0]{index=0}


1. What Is a Button in Flutter?

A button is an interactive widget that responds to user actions such as tapping, clicking, hovering, focusing, or long-pressing.

Common Button Actions

  • Submit a form
  • Open another screen
  • Save data
  • Delete data
  • Download content
  • Add an item to a cart
  • Open a menu
  • Search for information
  • Like or favorite an item
  • Start or stop an operation

Basic Button Structure

ElevatedButton(
  onPressed: () {
    print('Button clicked');
  },
  child: const Text('Click Me'),
)

Most standard Flutter buttons use an onPressed callback and a widget representing their content. :contentReference[oaicite:1]{index=1}


2. Main Types of Flutter Buttons

ButtonPurposeCommon Use
ElevatedButtonProminent filled button with elevationPrimary actions
FilledButtonProminent filled button without elevation emphasisPrimary actions
FilledButton.tonalTonal filled buttonSecondary actions
OutlinedButtonButton with an outline and no filled background by defaultSecondary actions
TextButtonSimple button without an outline or filled background by defaultLow-emphasis actions
IconButtonButton represented primarily by an iconToolbar and compact actions
FloatingActionButtonFloating prominent action buttonMain screen action

Material 3 defines five common button types: Elevated, Filled, Filled Tonal, Outlined, and Text. Flutter provides corresponding button implementations. :contentReference[oaicite:2]{index=2}


3. ElevatedButton

ElevatedButton is a filled button that provides visual elevation and is useful for prominent actions.

Basic Syntax

ElevatedButton(
  onPressed: () {
    print('Clicked');
  },
  child: const Text('Submit'),
)

Complete Example

import 'package:flutter/material.dart';

class ElevatedButtonExample extends StatelessWidget {
  const ElevatedButtonExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Elevated Button'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            print('Button pressed');
          },
          child: const Text('Submit'),
        ),
      ),
    );
  }
}

Flutter's ElevatedButton is intended to add visual prominence and elevation to an action. :contentReference[oaicite:3]{index=3}


4. Changing ElevatedButton Colors

ElevatedButton(
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    foregroundColor: Colors.white,
  ),
  onPressed: () {},
  child: const Text('Login'),
)
  • backgroundColor controls the button background.
  • foregroundColor controls text and icon color.

5. Changing Button Size

ElevatedButton(
  style: ElevatedButton.styleFrom(
    minimumSize: const Size(200, 50),
  ),
  onPressed: () {},
  child: const Text('Continue'),
)

Full Width Button

SizedBox(
  width: double.infinity,
  child: ElevatedButton(
    onPressed: () {},
    child: const Text('Continue'),
  ),
)

6. Button Padding

ElevatedButton(
  style: ElevatedButton.styleFrom(
    padding: const EdgeInsets.symmetric(
      horizontal: 30,
      vertical: 15,
    ),
  ),
  onPressed: () {},
  child: const Text('Submit'),
)

7. Button Border Radius

ElevatedButton(
  style: ElevatedButton.styleFrom(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(15),
    ),
  ),
  onPressed: () {},
  child: const Text('Rounded Button'),
)

Pill-Shaped Button

ElevatedButton(
  style: ElevatedButton.styleFrom(
    shape: const StadiumBorder(),
  ),
  onPressed: () {},
  child: const Text('Get Started'),
)

8. OutlinedButton

OutlinedButton displays an outlined button and is commonly used for secondary actions.

Basic Example

OutlinedButton(
  onPressed: () {
    print('Edit clicked');
  },
  child: const Text('Edit'),
)

Styled OutlinedButton

OutlinedButton(
  style: OutlinedButton.styleFrom(
    foregroundColor: Colors.blue,
    side: const BorderSide(
      color: Colors.blue,
      width: 2,
    ),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(12),
    ),
  ),
  onPressed: () {},
  child: const Text('Learn More'),
)

9. TextButton

TextButton is a low-emphasis button without a visible border or filled background by default. It is useful for actions such as Cancel, Skip, Learn More, or Edit.

Basic Example

TextButton(
  onPressed: () {
    print('Cancel clicked');
  },
  child: const Text('Cancel'),
)

Styled TextButton

TextButton(
  style: TextButton.styleFrom(
    foregroundColor: Colors.blue,
  ),
  onPressed: () {},
  child: const Text('Forgot Password?'),
)

Flutter documentation describes TextButton as appropriate for toolbars, dialogs, and inline actions where its placement provides enough context. :contentReference[oaicite:4]{index=4}


10. FilledButton

FilledButton is a filled Material button that does not use elevation as its primary visual distinction.

FilledButton(
  onPressed: () {},
  child: const Text('Save'),
)

Styled FilledButton

FilledButton(
  style: FilledButton.styleFrom(
    backgroundColor: Colors.green,
    foregroundColor: Colors.white,
  ),
  onPressed: () {},
  child: const Text('Save Changes'),
)

11. FilledButton.tonal

FilledButton.tonal provides a tonal filled appearance and can be useful for actions that need emphasis without looking as strong as a primary filled button.

FilledButton.tonal(
  onPressed: () {},
  child: const Text('View Details'),
)

12. TextButton vs ElevatedButton vs OutlinedButton

FeatureTextButtonElevatedButtonOutlinedButton
BackgroundTransparent by defaultFilledTransparent by default
BorderNo visible border by defaultNo visible border by defaultVisible outline
ElevationNo elevationUses elevationNo elevation
Typical UseLow-emphasis actionsProminent actionsSecondary actions
ExampleCancelSubmitLearn More

13. IconButton

IconButton is used when an icon itself represents an interactive action.

IconButton(
  icon: const Icon(Icons.favorite),
  onPressed: () {
    print('Favorite clicked');
  },
)

Styled IconButton

IconButton(
  icon: const Icon(Icons.favorite),
  iconSize: 35,
  color: Colors.red,
  onPressed: () {},
)

IconButton supports standard, filled, tonal, and outlined variants and can also be configured using an IconButtonTheme or its style. :contentReference[oaicite:5]{index=5}


14. IconButton with Tooltip

A tooltip can make an icon-only action easier to understand, especially when its purpose is not obvious.

IconButton(
  tooltip: 'Delete',
  icon: const Icon(Icons.delete),
  onPressed: () {
    print('Delete clicked');
  },
)

15. IconButton Toggle

An icon button can be used as a toggle to represent states such as favorite/unfavorite or selected/unselected.

bool isFavorite = false;

For a stateful implementation:

class FavoriteButton extends StatefulWidget {
  const FavoriteButton({super.key});

  @override
  State createState() =>
      _FavoriteButtonState();
}

class _FavoriteButtonState extends State {
  bool isFavorite = false;

  @override
  Widget build(BuildContext context) {
    return IconButton(
      isSelected: isFavorite,
      selectedIcon: const Icon(Icons.favorite),
      icon: const Icon(Icons.favorite_border),
      onPressed: () {
        setState(() {
          isFavorite = !isFavorite;
        });
      },
    );
  }
}

16. Buttons with Icons

Flutter provides convenient constructors such as ElevatedButton.icon(), FilledButton.icon(), OutlinedButton.icon(), and TextButton.icon().

ElevatedButton.icon

ElevatedButton.icon(
  onPressed: () {},
  icon: const Icon(Icons.download),
  label: const Text('Download'),
)

FilledButton.icon

FilledButton.icon(
  onPressed: () {},
  icon: const Icon(Icons.save),
  label: const Text('Save'),
)

OutlinedButton.icon

OutlinedButton.icon(
  onPressed: () {},
  icon: const Icon(Icons.edit),
  label: const Text('Edit'),
)

TextButton.icon

TextButton.icon(
  onPressed: () {},
  icon: const Icon(Icons.share),
  label: const Text('Share'),
)

17. FloatingActionButton

FloatingActionButton is commonly used for a primary action that should remain easily accessible on a screen.

Scaffold(
  body: const Center(
    child: Text('Home Screen'),
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {
      print('Add clicked');
    },
    child: const Icon(Icons.add),
  ),
)

FloatingActionButton with Tooltip

FloatingActionButton(
  tooltip: 'Add Item',
  onPressed: () {},
  child: const Icon(Icons.add),
)

18. FloatingActionButton.extended

The extended version can display both an icon and a text label.

FloatingActionButton.extended(
  onPressed: () {},
  icon: const Icon(Icons.add),
  label: const Text('Add Item'),
)

19. Button onPressed Callback

The onPressed callback defines what should happen when the button is activated.

ElevatedButton(
  onPressed: () {
    print('Hello Flutter');
  },
  child: const Text('Click'),
)

Calling a Function

void showMessage() {
  print('Button pressed');
}

ElevatedButton(
  onPressed: showMessage,
  child: const Text('Click'),
)

20. Passing Parameters to a Function

void showUser(String name) {
  print('Hello $name');
}

ElevatedButton(
  onPressed: () {
    showUser('Rahul');
  },
  child: const Text('Welcome'),
)

21. Disabling a Button

A button can be disabled by setting onPressed to null.

ElevatedButton(
  onPressed: null,
  child: const Text('Disabled'),
)

For standard Material buttons, a null onPressed and onLongPress causes the button to be disabled. :contentReference[oaicite:6]{index=6}


22. Conditional Button State

bool isEnabled = true;

ElevatedButton(
  onPressed: isEnabled
      ? () {
          print('Button clicked');
        }
      : null,
  child: const Text('Submit'),
)

Practical Example

class SubmitButton extends StatefulWidget {
  const SubmitButton({super.key});

  @override
  State createState() => _SubmitButtonState();
}

class _SubmitButtonState extends State {
  bool isLoading = false;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: isLoading
          ? null
          : () async {
              setState(() {
                isLoading = true;
              });

              await Future.delayed(
                const Duration(seconds: 2),
              );

              setState(() {
                isLoading = false;
              });
            },
      child: isLoading
          ? const SizedBox(
              width: 20,
              height: 20,
              child: CircularProgressIndicator(
                strokeWidth: 2,
              ),
            )
          : const Text('Submit'),
    );
  }
}

23. ButtonStyle

ButtonStyle is used to control the appearance and behavior-related visual properties of Material buttons. It can define properties such as colors, padding, shape, minimum size, borders, and state-dependent visual behavior. :contentReference[oaicite:7]{index=7}

Example

ElevatedButton(
  style: ButtonStyle(
    backgroundColor: WidgetStatePropertyAll(
      Colors.blue,
    ),
    foregroundColor: WidgetStatePropertyAll(
      Colors.white,
    ),
    padding: WidgetStatePropertyAll(
      EdgeInsets.symmetric(
        horizontal: 25,
        vertical: 15,
      ),
    ),
  ),
  onPressed: () {},
  child: const Text('Submit'),
)

24. Using styleFrom()

The styleFrom() methods provide a convenient way to create button styles using straightforward property values.

ElevatedButton(
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.green,
    foregroundColor: Colors.white,
    padding: const EdgeInsets.symmetric(
      horizontal: 30,
      vertical: 15,
    ),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(12),
    ),
  ),
  onPressed: () {},
  child: const Text('Register'),
)

Flutter provides styleFrom() methods for common Material button classes, including ElevatedButton, FilledButton, OutlinedButton, and TextButton. :contentReference[oaicite:8]{index=8}


25. Button Shape

Rounded Rectangle

ElevatedButton(
  style: ElevatedButton.styleFrom(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(20),
    ),
  ),
  onPressed: () {},
  child: const Text('Rounded'),
)

Stadium Shape

ElevatedButton(
  style: ElevatedButton.styleFrom(
    shape: const StadiumBorder(),
  ),
  onPressed: () {},
  child: const Text('Pill Button'),
)

26. Button Border

Outlined buttons are especially useful when you want to emphasize a border.

OutlinedButton(
  style: OutlinedButton.styleFrom(
    side: const BorderSide(
      color: Colors.blue,
      width: 2,
    ),
  ),
  onPressed: () {},
  child: const Text('Outlined'),
)

27. Button Text Styling

ElevatedButton(
  style: ElevatedButton.styleFrom(
    textStyle: const TextStyle(
      fontSize: 18,
      fontWeight: FontWeight.bold,
    ),
  ),
  onPressed: () {},
  child: const Text('Submit'),
)

28. Button Elevation

ElevatedButton can be customized with an elevation value.

ElevatedButton(
  style: ElevatedButton.styleFrom(
    elevation: 8,
  ),
  onPressed: () {},
  child: const Text('Elevated'),
)

29. Button Minimum Size

ElevatedButton(
  style: ElevatedButton.styleFrom(
    minimumSize: const Size(180, 50),
  ),
  onPressed: () {},
  child: const Text('Continue'),
)

30. Button Maximum Size

ElevatedButton(
  style: ElevatedButton.styleFrom(
    maximumSize: const Size(300, 60),
  ),
  onPressed: () {},
  child: const Text('Continue'),
)

31. Full Width Login Button

Padding(
  padding: const EdgeInsets.symmetric(horizontal: 20),
  child: SizedBox(
    width: double.infinity,
    child: ElevatedButton(
      onPressed: () {
        print('Login');
      },
      child: const Text('Login'),
    ),
  ),
)

32. Login Screen Buttons Example

Column(
  children: [
    SizedBox(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: () {
          print('Login');
        },
        child: const Text('Login'),
      ),
    ),
    const SizedBox(height: 10),
    SizedBox(
      width: double.infinity,
      child: OutlinedButton(
        onPressed: () {
          print('Create account');
        },
        child: const Text('Create Account'),
      ),
    ),
    const SizedBox(height: 10),
    TextButton(
      onPressed: () {
        print('Forgot password');
      },
      child: const Text('Forgot Password?'),
    ),
  ],
)

33. Save, Edit, and Delete Buttons

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    ElevatedButton.icon(
      onPressed: () {},
      icon: const Icon(Icons.save),
      label: const Text('Save'),
    ),
    OutlinedButton.icon(
      onPressed: () {},
      icon: const Icon(Icons.edit),
      label: const Text('Edit'),
    ),
    IconButton(
      tooltip: 'Delete',
      icon: const Icon(Icons.delete),
      color: Colors.red,
      onPressed: () {},
    ),
  ],
)

34. Button with Loading Indicator

A loading state is useful when a button starts an asynchronous operation.

ElevatedButton(
  onPressed: () async {
    print('Processing...');
  },
  child: const SizedBox(
    width: 20,
    height: 20,
    child: CircularProgressIndicator(
      strokeWidth: 2,
    ),
  ),
)

Dynamic Loading Button

class LoadingButton extends StatefulWidget {
  const LoadingButton({super.key});

  @override
  State createState() => _LoadingButtonState();
}

class _LoadingButtonState extends State {
  bool loading = false;

  Future submit() async {
    setState(() {
      loading = true;
    });

    await Future.delayed(
      const Duration(seconds: 2),
    );

    if (mounted) {
      setState(() {
        loading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: loading ? null : submit,
      child: loading
          ? const SizedBox(
              width: 20,
              height: 20,
              child: CircularProgressIndicator(
                strokeWidth: 2,
              ),
            )
          : const Text('Submit'),
    );
  }
}

35. Buttons Inside Cards

Card(
  child: Padding(
    padding: const EdgeInsets.all(16),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'Flutter Course',
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 10),
        const Text(
          'Learn Flutter application development.',
        ),
        const SizedBox(height: 15),
        Row(
          children: [
            Expanded(
              child: ElevatedButton(
                onPressed: () {},
                child: const Text('Enroll'),
              ),
            ),
            const SizedBox(width: 10),
            Expanded(
              child: OutlinedButton(
                onPressed: () {},
                child: const Text('Details'),
              ),
            ),
          ],
        ),
      ],
    ),
  ),
)

36. Buttons Inside a Dialog

showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      title: const Text('Delete Item'),
      content: const Text(
        'Are you sure you want to delete this item?',
      ),
      actions: [
        TextButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Cancel'),
        ),
        ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Delete'),
        ),
      ],
    );
  },
);

37. Buttons and Navigation

Buttons are frequently used to navigate from one screen to another.

ElevatedButton(
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const SecondScreen(),
      ),
    );
  },
  child: const Text('Open Next Screen'),
)

Complete Example

class SecondScreen extends StatelessWidget {
  const SecondScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Second Screen'),
      ),
      body: const Center(
        child: Text('Welcome to Second Screen'),
      ),
    );
  }
}

38. Buttons with Form Validation

Buttons are commonly used to submit a Form.

final formKey = GlobalKey();

Form(
  key: formKey,
  child: Column(
    children: [
      TextFormField(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please enter your name';
          }
          return null;
        },
        decoration: const InputDecoration(
          labelText: 'Name',
        ),
      ),
      const SizedBox(height: 20),
      ElevatedButton(
        onPressed: () {
          if (formKey.currentState!.validate()) {
            print('Form is valid');
          }
        },
        child: const Text('Submit'),
      ),
    ],
  ),
)

39. Creating a Custom Reusable Button

When the same button design is used throughout an application, creating a reusable custom widget can reduce duplicate code.

class PrimaryButton extends StatelessWidget {
  final String text;
  final VoidCallback onPressed;

  const PrimaryButton({
    super.key,
    required this.text,
    required this.onPressed,
  });

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: onPressed,
        child: Text(text),
      ),
    );
  }
}

Using the Custom Button

PrimaryButton(
  text: 'Login',
  onPressed: () {
    print('Login clicked');
  },
)

40. Creating a Reusable Icon Button

class ActionIconButton extends StatelessWidget {
  final IconData icon;
  final String tooltip;
  final VoidCallback onPressed;

  const ActionIconButton({
    super.key,
    required this.icon,
    required this.tooltip,
    required this.onPressed,
  });

  @override
  Widget build(BuildContext context) {
    return IconButton(
      tooltip: tooltip,
      icon: Icon(icon),
      onPressed: onPressed,
    );
  }
}

Using the Widget

ActionIconButton(
  icon: Icons.delete,
  tooltip: 'Delete',
  onPressed: () {
    print('Delete');
  },
)

41. Theming Buttons Globally

Instead of styling every button separately, button themes can be configured in ThemeData. Flutter provides separate themes for button types such as ElevatedButtonTheme, OutlinedButtonTheme, and TextButtonTheme. :contentReference[oaicite:9]{index=9}

MaterialApp(
  theme: ThemeData(
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      ),
    ),
  ),
  home: const HomeScreen(),
)

Now ElevatedButtons throughout the relevant application theme can use the configured styling unless a local style overrides it.


42. Button States

Buttons can have different visual states depending on user interaction.

StateDescription
EnabledButton can be activated.
DisabledButton cannot be activated.
PressedUser is currently pressing the button.
HoveredPointer is positioned over the button, especially relevant on desktop/web.
FocusedButton has keyboard or accessibility focus.
SelectedUsed by supported controls to represent a selected state.

Flutter's button styling system supports state-dependent values through state properties. :contentReference[oaicite:10]{index=10}


43. State-Dependent Button Styling

For advanced designs, a button's style can respond differently to pressed, hovered, focused, or other widget states.

ElevatedButton(
  style: ButtonStyle(
    backgroundColor: WidgetStateProperty.resolveWith(
      (states) {
        if (states.contains(WidgetState.pressed)) {
          return Colors.blue.shade900;
        }
        if (states.contains(WidgetState.hovered)) {
          return Colors.blue.shade700;
        }
        return Colors.blue;
      },
    ),
  ),
  onPressed: () {},
  child: const Text('Interactive Button'),
)

44. Button Alignment

Buttons can be aligned using layout widgets.

Center Button

Center(
  child: ElevatedButton(
    onPressed: () {},
    child: const Text('Center'),
  ),
)

Right-Aligned Button

Align(
  alignment: Alignment.centerRight,
  child: ElevatedButton(
    onPressed: () {},
    child: const Text('Continue'),
  ),
)

45. Multiple Buttons in a Row

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    ElevatedButton(
      onPressed: () {},
      child: const Text('Save'),
    ),
    const SizedBox(width: 10),
    OutlinedButton(
      onPressed: () {},
      child: const Text('Cancel'),
    ),
  ],
)

46. Multiple Buttons in a Column

Column(
  children: [
    SizedBox(
      width: double.infinity,
      child: ElevatedButton(
        onPressed: () {},
        child: const Text('Login'),
      ),
    ),
    const SizedBox(height: 10),
    SizedBox(
      width: double.infinity,
      child: OutlinedButton(
        onPressed: () {},
        child: const Text('Register'),
      ),
    ),
    TextButton(
      onPressed: () {},
      child: const Text('Forgot Password?'),
    ),
  ],
)

47. Complete Buttons Example

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Buttons',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
        ),
        useMaterial3: true,
      ),
      home: const ButtonsScreen(),
    );
  }
}

class ButtonsScreen extends StatelessWidget {
  const ButtonsScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Buttons'),
        actions: [
          IconButton(
            tooltip: 'Search',
            icon: const Icon(Icons.search),
            onPressed: () {},
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            ElevatedButton(
              onPressed: () {
                print('Elevated button');
              },
              child: const Text('Elevated Button'),
            ),
            const SizedBox(height: 15),
            FilledButton(
              onPressed: () {
                print('Filled button');
              },
              child: const Text('Filled Button'),
            ),
            const SizedBox(height: 15),
            FilledButton.tonal(
              onPressed: () {
                print('Tonal button');
              },
              child: const Text('Tonal Button'),
            ),
            const SizedBox(height: 15),
            OutlinedButton(
              onPressed: () {
                print('Outlined button');
              },
              child: const Text('Outlined Button'),
            ),
            const SizedBox(height: 15),
            TextButton(
              onPressed: () {
                print('Text button');
              },
              child: const Text('Text Button'),
            ),
            const SizedBox(height: 15),
            ElevatedButton.icon(
              onPressed: () {
                print('Download');
              },
              icon: const Icon(Icons.download),
              label: const Text('Download'),
            ),
            const SizedBox(height: 15),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                IconButton(
                  tooltip: 'Favorite',
                  icon: const Icon(Icons.favorite_border),
                  onPressed: () {},
                ),
                IconButton(
                  tooltip: 'Share',
                  icon: const Icon(Icons.share),
                  onPressed: () {},
                ),
                IconButton(
                  tooltip: 'Delete',
                  icon: const Icon(Icons.delete),
                  color: Colors.red,
                  onPressed: () {},
                ),
              ],
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        tooltip: 'Add',
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
    );
  }
}

48. Button Selection Guide

RequirementRecommended Widget
Main important actionElevatedButton or FilledButton
Secondary actionOutlinedButton
Low-emphasis actionTextButton
Action represented by an iconIconButton
Main floating screen actionFloatingActionButton
Action with icon and textElevatedButton.icon, FilledButton.icon, OutlinedButton.icon, or TextButton.icon
Tonal filled actionFilledButton.tonal

49. Old Flutter Buttons vs Modern Buttons

Old WidgetModern Replacement
FlatButtonTextButton
RaisedButtonElevatedButton
OutlineButtonOutlinedButton

The older Material button widgets were deprecated and replaced by the newer button classes. New Flutter applications should use the current button APIs. :contentReference[oaicite:11]{index=11}


50. Button Accessibility Best Practices

  • Use clear and meaningful button labels.
  • Use tooltips for icon-only actions where appropriate.
  • Do not make important actions depend only on color.
  • Maintain sufficient contrast between button content and its background.
  • Provide an adequate interactive area for touch controls.
  • Use disabled states only when the action genuinely cannot be performed.
  • Make button behavior predictable.
  • Use semantic labels when the visual content alone does not communicate the action clearly.

Example

IconButton(
  tooltip: 'Delete account',
  icon: const Icon(Icons.delete),
  onPressed: () {},
)

51. Button Design Best Practices

  • Use one visually prominent primary action where appropriate.
  • Use consistent button shapes throughout the application.
  • Keep button labels short and action-oriented.
  • Use icons when they improve recognition of the action.
  • Avoid placing too many competing primary buttons together.
  • Use loading indicators when an action takes noticeable time.
  • Disable buttons when an action cannot currently be performed.
  • Use reusable custom button widgets for repeated designs.
  • Use application-level button themes for consistent styling.
  • Prefer current Flutter button widgets instead of deprecated button APIs.

52. Common Mistakes

Mistake 1: Forgetting onPressed

ElevatedButton(
  child: const Text('Submit'),
)

The standard constructor requires an onPressed callback.

Correct Version

ElevatedButton(
  onPressed: () {},
  child: const Text('Submit'),
)

Mistake 2: Using Deprecated Button Widgets

Avoid starting new projects with FlatButton, RaisedButton, or OutlineButton. Use their modern replacements.

Mistake 3: Using Too Many Colors

Using a different button color for every action can make the interface inconsistent. Use a clear visual hierarchy.

Mistake 4: Ignoring Disabled State

If an action cannot currently be performed, provide an appropriate disabled state instead of allowing the user to trigger an invalid operation.

Mistake 5: Using IconButton Without Context

An unfamiliar icon may not clearly communicate its purpose. Add a tooltip or supporting context when appropriate.


53. Practice Exercises

  1. Create a screen containing ElevatedButton, FilledButton, OutlinedButton, and TextButton.
  2. Create a login screen with Login and Register buttons.
  3. Create a registration form with a Submit button.
  4. Create a product card with Add to Cart and Favorite buttons.
  5. Create an AppBar with Search, Notifications, and Settings IconButtons.
  6. Create a delete confirmation dialog containing Cancel and Delete buttons.
  7. Create a loading Submit button using setState().
  8. Create a custom reusable primary button.
  9. Create a FloatingActionButton for adding a new item.
  10. Create a button that navigates from one screen to another.
  11. Create a favorite button that changes between favorite and favorite-border icons.
  12. Create a global button theme using ThemeData.

54. Interview Questions

  1. What is a button in Flutter?
  2. What are the main button widgets in Flutter?
  3. What is the difference between ElevatedButton and FilledButton?
  4. What is the difference between ElevatedButton and OutlinedButton?
  5. When should you use TextButton?
  6. What is IconButton?
  7. What is FloatingActionButton?
  8. How do you disable a Flutter button?
  9. What is the purpose of the onPressed property?
  10. How do you add an icon to an ElevatedButton?
  11. What is ButtonStyle?
  12. What is the purpose of styleFrom()?
  13. How do you change a button's background color?
  14. How do you change a button's border?
  15. How do you create a rounded button?
  16. How do you create a full-width button?
  17. How do you create a reusable custom button?
  18. How can button styles respond to pressed or hovered states?
  19. How can you show a loading indicator inside a button?
  20. Which old Flutter button widgets have been replaced by modern button widgets?

55. Key Takeaways

  • Buttons provide interaction between the user and the application.
  • ElevatedButton is useful for prominent actions.
  • FilledButton provides a prominent filled Material 3 button.
  • FilledButton.tonal provides a tonal filled button.
  • OutlinedButton is useful for secondary actions.
  • TextButton is useful for low-emphasis actions.
  • IconButton is useful for compact icon-based actions.
  • FloatingActionButton is useful for a prominent floating action.
  • ButtonStyle provides advanced button customization.
  • styleFrom() provides a convenient way to create common button styles.
  • Buttons can contain both text and icons.
  • Buttons can be enabled, disabled, pressed, hovered, focused, or selected depending on the widget and configuration.
  • Button themes help maintain consistent application-wide styling.
  • Use current Flutter button APIs instead of deprecated button widgets.

56. Learning Resources

JustAcademy Flutter Training: Flutter Training

Register for Course Demo: Register for Course Demo

Official Flutter Button Styling Documentation: ButtonStyle API

Official ElevatedButton Documentation: ElevatedButton API

Official TextButton Documentation: TextButton API

Official IconButton Documentation: IconButton API

Official Flutter Interactivity Guide: Adding Interactivity to Your Flutter App

whatsapp